package com.xiaode.interceptor;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.Ret;
import com.jfinal.kit.ThreadPoolKit;
import com.jfinal.plugin.redis.Redis;
import com.xiaode.common.UserTokenManager;
import com.xiaode.common.constant.Const;
import com.xiaode.common.model.Admin;
import com.xiaode.common.model.Student;
import com.xiaode.common.model.dto.log.UserSLogDTO;
import com.xiaode.common.model.dto.log.UserTLogDTO;
import com.xiaode.exce.EnumError;
import com.xiaode.plugin.influx.InfluxDbKit;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Map;

/**
 * app用户登录拦截
 */
public class AppLoginInterceptor implements Interceptor {

	@Override
	public void intercept(Invocation inv) {
		Controller c = inv.getController();
		String token = c.getHeader("token");
		if (StrUtil.isBlank(token)) {
			c.renderJson(Ret.fail().set("error", EnumError.APP_USER_TOKEN_ERROR.getObj()));
			return;
		}
		Integer accountId = Redis.use().get("userToken:"+token);
		if(accountId == null) {
			c.renderJson(Ret.fail().set("error", EnumError.APP_USER_TOKEN_ERROR.getObj()));
			return;
		}
		String tokenInfo = UserTokenManager.getInfo(token);
		if (StrUtil.isBlank(tokenInfo)) {
			c.renderJson(Ret.fail().set("error", EnumError.APP_USER_TOKEN_ERROR.getObj()));
			return;
		}
		JSONObject tokenInfoJ = JSONUtil.parseObj(tokenInfo);
		accountId = tokenInfoJ.getInt("accountId");
		Integer userType = tokenInfoJ.getInt("userType");
		String account = tokenInfoJ.getStr("account");
		Integer userId = tokenInfoJ.getInt("userId");
		
		if (userType == Const.UserType.admin) {
	        Boolean b = Redis.use().exists(Const.user.loginAdmin + accountId);
	        if (!b) {
	            c.renderJson(Ret.fail().set("error", EnumError.APP_USER_TOKEN_ERROR.getObj()));
	            return;
	        }
	        Admin admin = Redis.use().get(Const.user.loginAdmin + accountId);
	        if (BeanUtil.isEmpty(admin)) {
	            c.renderJson(Ret.fail().set("error", EnumError.ACCOUNT_NO.getObj()));
	            return;
	        }
	        if (admin.getState() != 1) {
	            c.renderJson(Ret.fail().set("error", EnumError.ACCOUNT_PROHIBIT.getObj()));
	            return;
	        }
	        //更新上次使用时间
	        Redis.use().zadd(Const.user.lastLoginTimeT, LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), admin.getId());//存最后登陆时间
	        Redis.use().set(Const.user.loginAdmin + admin.getId(), admin);
	        
	        c.setAttr("user", admin).setAttr("accountId", accountId).setAttr("userId", userId).setAttr("userType", userType).setAttr("account", account);
		} else if (userType == Const.UserType.student) {
	        Boolean b = Redis.use().exists(Const.user.loginStudent + accountId);
	        if (!b) {
	            c.renderJson(Ret.fail().set("error", EnumError.APP_USER_TOKEN_ERROR.getObj()));
	            return;
	        }
	        Student student = Redis.use().get(Const.user.loginStudent + accountId);
	        if (BeanUtil.isEmpty(student)) {
	            c.renderJson(Ret.fail().set("error", EnumError.ACCOUNT_NO.getObj()));
	            return;
	        }
	        if (student.getState() != 1) {
	            c.renderJson(Ret.fail().set("error", EnumError.ACCOUNT_PROHIBIT.getObj()));
	            return;
	        }
	        //更新上次使用时间
	        Redis.use().zadd(Const.user.lastLoginTimeS, LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(), student.getId());//存最后登陆时间
	        Redis.use().set(Const.user.loginStudent + student.getId(), student);
		
	        c.setAttr("user", student).setAttr("accountId", accountId).setAttr("userId", userId).setAttr("userType", userType).setAttr("account", account);
		}

		inv.invoke();

		if (userType == Const.UserType.admin) {
			Admin admin = Redis.use().get(Const.user.loginAdmin + accountId);
			// 存入日志添加判断不是所有都做记录，比如：轮询的接口不要记录
			ThreadPoolKit.execute(() -> {
				try {
					UserTLogDTO tlog = new UserTLogDTO();
					HttpServletRequest request = c.getRequest();
					Map<String, String[]> parameterMap = request.getParameterMap();
					String para = JSONUtil.toJsonStr(parameterMap);
					tlog.setMethodName(inv.getMethodName());
					String actionKey = inv.getActionKey();

					if (actionKey.startsWith("/tExample")) {
						tlog.setModularType(Const.modularType.ADMIN_EXAMPLE_MODULAR);
					} else if (actionKey.startsWith("/task")) {
						tlog.setModularType(Const.modularType.ADMIN_TASK_MODULAR);
					} else if (actionKey.startsWith("/tMessage")) {
						tlog.setModularType(Const.modularType.ADMIN_MESSAGE_MODULAR);
					} else if (actionKey.startsWith("/user")) {
						tlog.setModularType(Const.modularType.ADMIN_USER_MODULAR);
					}
					tlog.setPara(para);
					tlog.setRemortIP(getRemortIP(request));

					tlog.setUrl(inv.getActionKey());
					tlog.setUserId(admin.getId());
					tlog.setExtras(null);
					InfluxDbKit.insertAsyn(tlog);
					tlog = null;

				} catch (Exception e) {
					e.printStackTrace();
				}
			});
		} else if (userType == Const.UserType.student) {
			Student student = Redis.use().get(Const.user.loginStudent + accountId);
			// 存入日志 添加判断不是所有都做记录，比如：轮询的接口不要记录
			ThreadPoolKit.execute(() -> {
				try {
					UserSLogDTO slog = new UserSLogDTO();
					HttpServletRequest request = c.getRequest();
					Map<String, String[]> parameterMap = request.getParameterMap();
					String para = JSONUtil.toJsonStr(parameterMap);
					slog.setMethodName(inv.getMethodName());
					String actionKey = inv.getActionKey();

					if (actionKey.startsWith("/sExample")) {
						slog.setModularType(Const.modularType.STUDENT_EXAMPLE_MODULAR);
					} else if (actionKey.startsWith("/task")) {
						slog.setModularType(Const.modularType.STUDENT_TASK_MODULAR);
					} else if (actionKey.startsWith("/sMessage")) {
						slog.setModularType(Const.modularType.STUDENT_MESSAGE_MODULAR);
					} else if (actionKey.startsWith("/user")) {
						slog.setModularType(Const.modularType.STUDENT_USER_MODULAR);
					}

					slog.setPara(para);
					slog.setRemortIP(getRemortIP(request));
					slog.setUrl(inv.getActionKey());
					slog.setUserId(student.getId());
					slog.setExtras(null);
					InfluxDbKit.insertAsyn(slog);
					slog = null;

				} catch (Exception e) {
					e.printStackTrace();
				}
			});
		} else if (userType == Const.UserType.parent) {

		}
		
		
		

	}

	/**
	 * 获取客户端ip
	 */
	public String getRemortIP(HttpServletRequest request) {
		if (request.getHeader("x-forwarded-for") == null
				|| request.getHeader("x-forwarded-for").split(",")[0].equals("127.0.0.1")) {
			return request.getRemoteAddr();
		}
		return request.getHeader("x-forwarded-for").split(",")[0];
	}
}
